﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using PloobsEngine;
using PloobsEngine.Cameras;
using PloobsEngine.Features;
using PloobsEngine.Input;
using PloobsEngine.Light;
using PloobsEngine.Material;
using PloobsEngine.Modelo;
using PloobsEngine.Physics;
using PloobsEngine.Physics.XJigLib;
using PloobsEngine.SceneControl;
using PloobsEngineDemo3;
using Visu;
using ZedGraph;

namespace Etapa1.Screens
{
    /// <summary>
    /// Data Aquisition and various Materials
    /// </summary>
    public class DataAq : SceneScreen
    {
        private JigLibxWorld physicWorld;
        private BrutalForceWorld mundo;
        private EngineStuff engine;        
        private ICamera cam;
        private FPSCounter fp;
        private int i = 0;
        GraphController l;
                
        public DataAq(EngineStuff es)
        {
            this.engine = es;                       
            physicWorld = new JigLibxWorld(new GenericDebugDrawn(engine));            
            mundo = new BrutalForceWorld(physicWorld);                     
        }

        /// <summary>
        /// Override do Metodo da Screen para alimentar o grafico com pontos
        /// </summary>
        /// <param name="gameTime"></param>
        /// <param name="otherScreenHasFocus"></param>
        /// <param name="coveredByOtherScreen"></param>
        public override void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen)
        {            
            l.FormThread.addPoint("My Curve", i++ , fp.FPS);            

            base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
        }

        public override void LoadContent(EngineStuff es)
        {            
            InputAdvanced inp = new InputAdvanced(engine);
            engine.AddComponent(inp);

            fp = new FPSCounter(engine);
            engine.AddComponent(fp);

            base.LoadContent(es);

            #region Cenario

            {
                SimpleModel sm = new SimpleModel("..\\Content\\Model\\factory");
                sm.LoadModelo();                
                IPhysicObject pi = new TriangleMeshObject(sm, Matrix.Identity, Vector3.Zero);
                pi.isMotionLess = true;
                NormalDeferred shader = new NormalDeferred();
                shader.SpecularIntensity = 0.1f;
                shader.SpecularPower = 0.3f;
                shader.Initialize();
                IMaterial mat = new Material(shader);
                IObject obj4 = new SimpleObject(mat, pi, sm);
                mundo.AddObject(obj4);
            }

            {
                SimpleModel sm = new SimpleModel("..\\Content\\Model\\grass");
                sm.BumpMapName = "..\\Content\\Textures\\grass_normal";
                sm.DiffuseMapName = "..\\Content\\Textures\\grass";
                sm.SpecularMapName = "..\\Content\\Textures\\grass_specular";
                sm.LoadModelo();
                IPhysicObject pi = new TriangleMeshObject(sm, Matrix.Identity, Vector3.Zero);
                pi.isMotionLess = true;
                CustomDeferred shader = new CustomDeferred(false, true, true, false);                                
                shader.Initialize();
                IMaterial mat = new Material(shader);
                IObject obj4 = new SimpleObject(mat, pi, sm);
                mundo.AddObject(obj4);
            }

            {
                SimpleModel sm = new SimpleModel("..\\Content\\Model\\factory_interior");
                sm.DiffuseMapName = "..\\Content\\Textures\\chao";
                sm.LoadModelo();
                IPhysicObject pi = new TriangleMeshObject(sm, Matrix.Identity, Vector3.Zero);
                pi.isMotionLess = true;
                NormalDeferred shader = new NormalDeferred();
                shader.Initialize();
                IMaterial mat = new Material(shader);
                IObject obj4 = new SimpleObject(mat, pi, sm);
                mundo.AddObject(obj4);
            }

            {
                SimpleModel sm = new SimpleModel("..\\Content\\Model\\door");
                sm.DiffuseMapName = "..\\Content\\Textures\\chao";
                sm.LoadModelo();
                IPhysicObject pi = new TriangleMeshObject(sm, Matrix.Identity, Vector3.Zero);
                pi.isMotionLess = true;
                NormalDeferred shader = new NormalDeferred();
                shader.Initialize();
                IMaterial mat = new Material(shader);
                IObject obj4 = new SimpleObject(mat, pi, sm);
                mundo.AddObject(obj4);
            }

            {
                SimpleModel sm = new SimpleModel("..\\Content\\Model\\cilos");
                sm.DiffuseMapName = "..\\Content\\Textures\\oilank";
                sm.LoadModelo();
                IPhysicObject pi = new TriangleMeshObject(sm, Matrix.Identity, Vector3.Zero);
                pi.isMotionLess = true;
                EMReflective shader = new EMReflective("..\\Content\\Textures\\cubeMap",ReflectionType.PerfectMirror);
                shader.SpecularPower = 0.1f;
                shader.SpecularIntensity = 0.1f;                
                shader.Initialize();
                IMaterial mat = new Material(shader);
                IObject obj4 = new SimpleObject(mat, pi, sm);
                mundo.AddObject(obj4);

            }

            {
                SimpleModel sm = new SimpleModel("..\\Content\\Model\\chao");
                sm.DiffuseMapName = "..\\Content\\Textures\\chao";
                sm.LoadModelo();
                IPhysicObject pi = new TriangleMeshObject(sm, Matrix.Identity, Vector3.Zero);
                pi.isMotionLess = true;
                NormalDeferred shader = new NormalDeferred();
                shader.Initialize();
                IMaterial mat = new Material(shader);
                IObject obj4 = new SimpleObject(mat, pi, sm);
                mundo.AddObject(obj4);
            }

            {
                SimpleModel sm = new SimpleModel("..\\Content\\Model\\pipe");
                sm.DiffuseMapName = "..\\Content\\Textures\\pipe";
                sm.LoadModelo();
                IPhysicObject pi = new TriangleMeshObject(sm, Matrix.Identity, Vector3.Zero);
                pi.isMotionLess = true;
                NormalDeferred shader = new NormalDeferred();
                shader.Initialize();
                IMaterial mat = new Material(shader);
                IObject obj4 = new SimpleObject(mat, pi, sm);
                mundo.AddObject(obj4);
            }

            {
                SimpleModel sm = new SimpleModel("..\\Content\\Model\\truck");
                sm.DiffuseMapName = "..\\Content\\Textures\\lorry";
                sm.GlowName = "..\\Content\\Textures\\lorry_glow";
                sm.LoadModelo();
                IPhysicObject pi = new TriangleMeshObject(sm, Matrix.Identity, Vector3.Zero);
                pi.isMotionLess = true;
                CustomDeferred shader = new CustomDeferred(true, false, false, false);                
                shader.Initialize();
                IMaterial mat = new Material(shader);
                IObject obj4 = new SimpleObject(mat, pi, sm);
                mundo.AddObject(obj4);
            }

            {
                SimpleModel sm = new SimpleModel("..\\Content\\Model\\caixa");
                sm.DiffuseMapName = "..\\Content\\Textures\\diffuse";
                sm.GlowName = "..\\Content\\Textures\\glow";
                sm.LoadModelo();
                IPhysicObject pi = new TriangleMeshObject(sm, Matrix.Identity, Vector3.Zero);
                pi.isMotionLess = true;
                CustomDeferred shader = new CustomDeferred(true, false, false, false);                
                shader.Initialize();
                IMaterial mat = new Material(shader);
                IObject obj4 = new SimpleObject(mat, pi, sm);
                mundo.AddObject(obj4);
            }

            {
                SimpleModel sm = new SimpleModel("..\\Content\\Model\\post");
                sm.LoadModelo();
                IPhysicObject pi = new TriangleMeshObject(sm, Matrix.Identity, Vector3.Zero);
                pi.isMotionLess = true;                
                EMReflective shader = new EMReflective("..\\Content\\Textures\\cubeMap", 0.5f);
                shader.Initialize();
                IMaterial mat = new Material(shader);
                IObject obj4 = new SimpleObject(mat, pi, sm);
                mundo.AddObject(obj4);
            }

            #endregion

            cam = new CameraFirstPerson(true);            
            cam.FarPlane = 3000;            
            
            LightThrow lt = new LightThrow(mundo, engine);             

            #region NormalLight
            //Color color = new Color(48, 43, 123);
            Color color = Color.White;
            DirectionalLight ld1 = new DirectionalLight(Vector3.Left, color);
            DirectionalLight ld2 = new DirectionalLight(Vector3.Right, color);
            DirectionalLight ld3 = new DirectionalLight(Vector3.Backward, color);
            DirectionalLight ld4 = new DirectionalLight(Vector3.Forward, color);
            DirectionalLight ld5 = new DirectionalLight(Vector3.Down, color);
            float li = 0.4f;
            ld1.LightIntensity = li;
            ld2.LightIntensity = li;
            ld3.LightIntensity = li;
            ld4.LightIntensity = li;
            ld5.LightIntensity = li;
            mundo.AddLight(ld1);
            mundo.AddLight(ld2);
            mundo.AddLight(ld3);
            mundo.AddLight(ld4);
            mundo.AddLight(ld5);
            #endregion

            ////Criacao de uma Tecnica
            DeferredRenderTechnic dr = new DeferredRenderTechnic(engine);


            SSAOPostEffect s = new SSAOPostEffect();
            //s.OutputONLYSSAOMAP = true;
            s.BlurMode = BlurMode.SINGLE;            
            s.EnableControl = true;
            s.WhiteCorrection = 0.7f;
            s.Intensity = 5;
            s.Diffscale = 0.5f;
            dr.AddPostEffect(s);

          
            IRenderTechnic[] rt = new IRenderTechnic[] { dr };
            this.RenderTechnics = rt;
            mundo.AddCamera(cam);
            this.World = mundo;
            
            l = new GraphController(CreateGraph);
            while (l.Indication == false) ;///wait for the graph form complete loading


        }
        
        private static void CreateGraph(ZedGraphControl zgc)
        {
            GraphPane myPane = zgc.GraphPane;

            // Set the titles and axis labels
            myPane.Title.Text = "Performance Graph";
            myPane.XAxis.Title.Text = "Time";
            myPane.YAxis.Title.Text = "Fps";
            
            PointPairList list = new PointPairList();
            
            zgc.IsShowPointValues = true;

            LineItem myCurve = myPane.AddCurve("My Curve", list, System.Drawing.Color.Blue,
                                    SymbolType.None);
            // Fill the area under the curve with a white-red gradient at 45 degrees
            myCurve.Line.Fill = new Fill(System.Drawing.Color.White, System.Drawing.Color.Red, 45F);
                        

            // Make the symbols opaque by filling them with white
            myCurve.Symbol.Fill = new Fill(System.Drawing.Color.White);

            // Fill the axis background with a color gradient
            myPane.Chart.Fill = new Fill(System.Drawing.Color.White, System.Drawing.Color.LightGoldenrodYellow, 45F);

            // Fill the pane background with a color gradient
            myPane.Fill = new Fill(System.Drawing.Color.White, System.Drawing.Color.FromArgb(220, 220, 255), 45F);

            // Calculate the Axis Scale Ranges
            zgc.AxisChange();
        }
    }
}

